package com.zsxb.crm.aspect;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.zsxb.crm.context.BaseContext;
import com.zsxb.crm.mapper.MenuMapper;
import com.zsxb.crm.mapper.SystemLogMapper;
import com.zsxb.crm.pojo.Menu;
import com.zsxb.crm.pojo.TbSystemLog;
import com.zsxb.crm.utils.IpAddressUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class AutoFillLogAspect {
    @Autowired
    private SystemLogMapper logMapper;
    @Autowired
    private MenuMapper menuMapper;
//    @Autowired
//    private HttpServletRequest request;

    private final ObjectMapper objectMapper;

    public AutoFillLogAspect(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }


    @Pointcut("execution(* com.zsxb.crm.mapper.*.*(..)) && @annotation(com.zsxb.crm.annotation.Log)")
    public void logPointCut() {
    }

    // 返回通知，方法正常执行完毕后执行
    @AfterReturning(pointcut = "logPointCut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) throws Exception {
        // 获取当前请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String clientIp = IpAddressUtil.getClientIpAddress(request);

        log.info("---记录日志---");


        String url = request.getRequestURI();

        String[] split = url.split("/");

        Menu menu = menuMapper.queryByPath(split[2]);



        TbSystemLog systemLog = new TbSystemLog();

        systemLog.setTitle(menu.getMenuName());

        systemLog.setRequestMethod(request.getMethod()); // 获取HTTP请求方法


        //    businessType
        //    增  POST 1
        //    删  PUT  2
        //    改  DELETE  3

        String businessType = request.getMethod();
        if ("POST".equals(businessType)) {
            systemLog.setBusinessType(1);
        } else if ("PUT".equals(businessType)){
            systemLog.setBusinessType(2);
        } else if ("DELETE".equals(businessType)){
            systemLog.setBusinessType(3);
        } else {
            systemLog.setBusinessType(0);
        }

        systemLog.setMethod(joinPoint.getSignature().toShortString());
//        systemLog.setOperatorType(1);
        systemLog.setOperName(BaseContext.getCurrentId());
        // 记录url
        systemLog.setOperUrl(url);
//        systemLog.setOperIp(request.getRemoteAddr());
        systemLog.setOperIp(clientIp);
        systemLog.setOperLocation("XX XX");
//        systemLog.setOperParam(getArgsJson(joinPoint));
        systemLog.setOperParam(Arrays.toString(joinPoint.getArgs()));
        systemLog.setJsonResult(objectMapper.writeValueAsString(result));

        systemLog.setStatus(0);
        systemLog.setOperTime(LocalDateTime.now());


        log.info(String.valueOf(systemLog));

        logMapper.insert(systemLog);

    }

    // 异常通知，方法抛出异常时执行
    @AfterThrowing(pointcut = "logPointCut()", throwing = "exception")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable exception) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        TbSystemLog systemLog = new TbSystemLog();

        String url = request.getRequestURI();

        String[] split = url.split("/");

        Menu menu = menuMapper.queryByPath(split[2]);
        systemLog.setTitle(menu.getMenuName());
        // 业务类型
        String businessType = request.getMethod();
        if ("POST".equals(businessType)) {
            systemLog.setBusinessType(1);
        } else if ("PUT".equals(businessType)){
            systemLog.setBusinessType(2);
        } else if ("DELETE".equals(businessType)){
            systemLog.setBusinessType(3);
        } else {
            systemLog.setBusinessType(0);
        }
        // 业务类型列表
        systemLog.setBusinessTypes(null);
        // HTTP请求
        systemLog.setRequestMethod(request.getMethod());
        // 方法
        systemLog.setMethod(joinPoint.getSignature().toShortString());
        // 操作类型
//        systemLog.setOperatorType(1);
        // 操作人
        systemLog.setOperName(BaseContext.getCurrentId());
        // 部门名称
        systemLog.setDeptName("0");
        // 请求URL
        systemLog.setOperUrl(request.getRequestURI());
        // 请求IP
        systemLog.setOperIp(request.getRemoteAddr());
        // 位置，调API解析IP得到
        systemLog.setOperLocation("XX XX");
        // 请求参数
        systemLog.setOperParam(getArgsJson(joinPoint));

        // 状态
        systemLog.setStatus(1);
        // 错误信息  记录异常类型
        systemLog.setErrorMsg(exception.getClass().getName());

        log.error("日志记录异常: {}:", exception.getClass().getName());

        // 操作时间
        systemLog.setOperTime(LocalDateTime.now());


        logMapper.insert(systemLog);


    }

    // 获取请求参数并序列化为JSON格式
    private String getArgsJson(JoinPoint joinPoint) {
        try {
            Object[] args = joinPoint.getArgs();
            return objectMapper.writeValueAsString(args);
        } catch (Exception e) {
            return "参数序列化失败";
        }
    }


}